package com.ybkj.daijia.api.member.v4up;

import com.google.gson.Gson;
import com.ybkj.daijia.ServiceSetting;
import com.ybkj.daijia.serverUtils.ServiceUtil;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.api.member.SecurityUtils;
import com.ybkj.daijia.api.util.ErrorConstantV4;
import com.ybkj.daijia.api.util.ResultTransport;
import com.ybkj.daijia.common.Distance;
import com.ybkj.daijia.config.ErrandApi;
import com.ybkj.daijia.config.FreightApi;
import com.ybkj.daijia.config.ZhuanApi;
import com.ybkj.daijia.config.ZhuanxianApi;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.UsuallyEmploy;
import com.ybkj.daijia.server.model.UsuallyEmploy.ServiceType;
import com.ybkj.daijia.server.service.CompanyService;
import com.ybkj.daijia.server.service.CouponService;
import com.ybkj.daijia.server.service.DriverService;
import com.ybkj.daijia.server.service.GasDiscountService;
import com.ybkj.daijia.server.service.MemberService;
import com.ybkj.daijia.server.service.OrderService;
import com.ybkj.daijia.server.service.UsuallyEmployService;
import com.ybkj.daijia.server.service.ZhuancheService;
import com.ybkj.daijia.server.zhuan.Car;
import com.ybkj.daijia.server.zhuan.CarType;
import com.ybkj.daijia.server.zhuan.Order;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller("ProcessControllerV4up")
@RequestMapping(value = "passenger/api/rest/v4up")
public class ProcessController {

    private static final Logger logger = LoggerFactory.getLogger(ProcessController.class);
    SimpleDateFormat sd = com.ybkj.daijia.constant.DateConstant.DATE_TIME;
    @Autowired
    private MemberService memberService;
    @Autowired
    private DriverService driverService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private UsuallyEmployService usuallyEmployService;
    @Autowired
    private ZhuancheService zhuancheService;
    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;
    @Autowired
    private CouponService couponService;
    @Autowired
    private GasDiscountService gasDiscountService;
    @Autowired
    private ZhuanApi zhuanApi;
    @Autowired
    private ErrandApi errandApi;
    @Autowired
    private FreightApi freightApi;
    @Autowired
    private ZhuanxianApi zhuanxianApi;
    @Autowired
    private OrderService orderService;

    /**
     * 获取附近司机
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @param appKey
     * @param token     token令牌
     * @param timestamp 时间戳
     * @return
     */
    @RequestMapping(value = "queryNearEmploys", method = RequestMethod.GET)
    public @ResponseBody
    ResultTransport queryNearEmploys(
        String longitude, String latitude, String appKey, String token, String timestamp) {

        logger.error("recv longitude:{},latitude:{},appKey:{},token:{},timestamp:{}", longitude,
            latitude, appKey, token, timestamp);

        if (StringUtils.isBlank(longitude) || StringUtils.isBlank(latitude) || SecurityUtils
            .isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.PARAM_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(longitude);
        params.add(latitude);
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.TOKEN_ERROR);
        }

        try {

            Double lng = Double.valueOf(longitude);
            Double lat = Double.valueOf(latitude);

            List<Driver> drivers = driverService.queryNearDrivers(lng, lat, "zhuanche");

            Setting setting = settingUtils.get();

            List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(drivers)) {
                for (Driver driver : drivers) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("driverId", driver.getId());
                    map.put("driverName", driver.getName());
                    map.put("driverUserName", driver.getUsername());
                    map.put("driverHead",
                        setting.getWebUrl() + "/upload/driver/" + driver.getPhoto());
                    map.put("driverStarLevel", driver.getStarLevel());
                    map.put("driverDriveTimes", driver.getDriveTimes());
                    map.put("driverJialing", driver.getjialing());
                    map.put("driverDistance", driver.getDistanceStr());
                    map.put("driverMeter", driver.getDistance() * 1000);
                    map.put("driverStatus", driver.getStatus());
                    map.put("driverLng", driver.getLongitude());
                    map.put("driverLat", driver.getLatitude());

                    //car
                    if (null != driver.getCarId()) {
                        Car car = zhuancheService.findCar(driver.getCarId());
                        if (null != car) {
                            map.put("zhuan_carPhoto",
                                setting.getWebUrl() + "/upload/driverCar/" + car.getPicture());
                            map.put("zhuan_carName", car.getCarName());
                            map.put("zhuan_carNumber", car.getCarNumber());
                            map.put("zhuan_carTypeId", car.getCarTypeId());
                            String carTypeStr = "";
                            if (null != car.getCarTypeId()) {
                                CarType carType = zhuancheService.findCarType(car.getCarTypeId());
                                if (null != carType) {
                                    carTypeStr = carType.getTypeName();
                                }
                            }
                            map.put("zhuan_carTypeName", carTypeStr);
                        }
                    }
                    mapList.add(map);
                }
            }

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
            instance.setData(mapList);

            return instance;

        } catch (Exception e) {
            logger.error("api v4up queryNearEmploys error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }

    }

    /**
     * 手动添加常用司机
     * @record zhyu
     * @param appKey
     * @param token     token令牌
     * @param timestamp 时间戳
     *  乘客端收藏司机
     * @return
     */
    @RequestMapping(value = "addUsuallyEmploy", method = RequestMethod.POST)
    public synchronized @ResponseBody
    ResultTransport addUsuallyEmploy(
        Long employId, Long passengerId, String serviceType,
        String appKey, String token, String timestamp) {

        logger
            .debug("recv employId:{},passengerId:{},serviceType:{},appKey:{},token:{},timestamp:{}",
                employId, passengerId, serviceType, appKey, token, timestamp);

        if (null == employId || null == passengerId || StringUtils.isBlank(serviceType)
            || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.PARAM_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(employId));
        params.add(String.valueOf(passengerId));
        params.add(String.valueOf(serviceType));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.TOKEN_ERROR);
        }

        try {

            //生成常用司机记录
            UsuallyEmploy old = usuallyEmployService
                .findByEmployAndPassenger(employId, passengerId, ServiceType.valueOf(serviceType));
            if (null != old) {
                return ResultTransport.getErrorBy(ErrorConstantV4.USUALLY_EMPLOY_HAS_EXISTS);
            } else {
                UsuallyEmploy usuallyEmploy = new UsuallyEmploy();
                usuallyEmploy.setEmployId(employId);
                usuallyEmploy.setPassengerId(passengerId);
                usuallyEmploy.setServiceType(ServiceType.valueOf(serviceType));
                usuallyEmployService.insertRecord(usuallyEmploy);
            }

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);

            return instance;

        } catch (Exception e) {
            logger.error("api v4up addUsuallyEmploy error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }

    }

    /**
     * 删除常用司机
     *
     * @param phone     手机号
     * @param appKey
     * @param token     token令牌
     * @param timestamp 时间戳
     * @return
     */
    @RequestMapping(value = "deleteUsuallyEmploy", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport deleteUsuallyEmploy(
        Long passengerId, Long employId, String serviceType,
        String appKey, String token, String timestamp) {

        logger.debug("recv passengerId:{},employId:{},appKey:{},token:{},timestamp:{}", passengerId,
            employId, appKey, token, timestamp);

        if (null == passengerId || null == employId || StringUtils.isBlank(serviceType)
            || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.PARAM_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(passengerId));
        params.add(String.valueOf(employId));
        params.add(String.valueOf(serviceType));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.TOKEN_ERROR);
        }

        try {

            UsuallyEmploy old = usuallyEmployService
                .findByEmployAndPassenger(employId, passengerId, ServiceType.valueOf(serviceType));
            if (null != old) {
                usuallyEmployService.delete(old);
            }

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);

            return instance;

        } catch (Exception e) {
            logger.error("api v4up deleteUsuallyEmploy error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }

    }

    /**
     * 获取用户常用司机
     *
     * @param phone     手机号
     * @param appKey
     * @param token     token令牌
     * @param timestamp 时间戳
     * @return
     */
    @RequestMapping(value = "getUsuallyEmploys", method = RequestMethod.GET)
    public @ResponseBody
    ResultTransport getUsuallyEmploys(
        Long passengerId, String serviceType, Integer status, String longitude, String latitude,
        String appKey, String token, String timestamp) {

        //status 0空闲 1所有
        logger.debug(
            "recv passengerId:{},serviceType:{},status:{},longitude:{},latitude:{},appKey:{},token:{},timestamp:{}",
            passengerId, serviceType, status, longitude, latitude, appKey, token, timestamp);

        if (null == passengerId || null == status || null == longitude || null == longitude
            || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.PARAM_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(passengerId));
        params.add(String.valueOf(serviceType));
        params.add(String.valueOf(status));
        params.add(String.valueOf(longitude));
        params.add(String.valueOf(latitude));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.TOKEN_ERROR);
        }

        try {

            Double lng = Double.valueOf(longitude);
            Double lat = Double.valueOf(latitude);

            List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();

            List<UsuallyEmploy> usuallyEmploys = usuallyEmployService
                .getUsuallyEmploy(passengerId, serviceType);

            if (!CollectionUtils.isEmpty(usuallyEmploys)) {
                List<Driver> driverList = new ArrayList<>();
                for (UsuallyEmploy usually : usuallyEmploys) {
                    Driver driver = driverService.findOne(usually.getEmployId());
                    if (null != driver && !driver.getIsFreeze()) {
                        if (driver.getDriverJobType().contains(serviceType)) {
                            if ((status == 0 && driver.getStatus().equals(Driver.DRIVER_ONLINE))
                                || (status == 1)) {
                                //计算距离
                                double distance = Distance.doubleVal(lat, lng, driver.getLatitude(),
                                    driver.getLongitude());
                                driver.setDistance(distance);
                                DecimalFormat df = new DecimalFormat("#.00");
                                if (distance >= 1) {
                                    driver.setDistanceStr(df.format(distance) + "公里");
                                } else {
                                    driver.setDistanceStr((long) (distance * 1000) + "米");
                                }
                                driver.setServiceType(usually.getServiceType());
                                driverList.add(driver);
                            }
                        }
                    }
                }

                if (!CollectionUtils.isEmpty(driverList)) {
                    Collections.sort(driverList, new Comparator<Driver>() {
                        public int compare(Driver arg0, Driver arg1) {
                            return arg1.getStarLevel().compareTo(arg0.getStarLevel());
                        }
                    });

                    Collections.sort(driverList, new Comparator<Driver>() {
                        public int compare(Driver arg0, Driver arg1) {
                            return arg0.getDistance().compareTo(arg1.getDistance());
                        }
                    });

                    Collections.sort(driverList, new Comparator<Driver>() {
                        public int compare(Driver arg0, Driver arg1) {
                            if (!arg0.getStatus().equals(Driver.DRIVER_OFFLINE)) {
                                return arg0.getStatus().compareTo(arg1.getStatus());
                            }
                            return 1;
                        }
                    });

                    Setting setting = settingUtils.get();
                    for (Driver driver : driverList) {
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("driverId", driver.getId());
                        map.put("driverName", driver.getName());
                        map.put("driverUserName", driver.getUsername());
                        map.put("driverHead",
                            setting.getWebUrl() + "/upload/driver/" + driver.getPhoto());
                        map.put("driverStarLevel", driver.getStarLevel());
                        map.put("driverDriveTimes", driver.getDriveTimes());
                        map.put("driverJialing", driver.getjialing());
                        map.put("driverDistance", driver.getDistanceStr());
                        map.put("driverMeter", driver.getDistance() * 1000);
                        map.put("driverStatus", driver.getStatus());
                        map.put("driverLng", driver.getLongitude());
                        map.put("driverLat", driver.getLatitude());
                        map.put("driverServiceType", driver.getServiceType().toString());
                        if (null != driver.getCarId()) {
                            Car car = zhuancheService.findCar(driver.getCarId());
                            if (null != car) {
                                map.put("zhuan_carPhoto",
                                    setting.getWebUrl() + "/upload/driverCar/" + car.getPicture());
                                map.put("zhuan_carName", car.getCarName());
                                map.put("zhuan_carNumber", car.getCarNumber());
                                map.put("zhuan_carTypeId", car.getCarTypeId());
                                String carTypeStr = "";
                                if (null != car.getCarTypeId()) {
                                    CarType carType = zhuancheService
                                        .findCarType(car.getCarTypeId());
                                    if (null != carType) {
                                        carTypeStr = carType.getTypeName();
                                    }
                                }
                                map.put("zhuan_carTypeName", carTypeStr);
                            }
                        }

                        mapList.add(map);
                    }

                }

            }

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
            instance.setData(mapList);

            return instance;

        } catch (Exception e) {
            logger.error("api v4up getUsuallyEmploy error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }

    }

    /**
     * 查询未完成订单
     *
     * @param passengerId
     * @return
     */
    @RequestMapping(value = "queryPassengerUnFinishOrder", method = RequestMethod.GET)
    public @ResponseBody
    ResultTransport queryPassengerUnFinishOrder(Long passengerId) {
        ResultTransport resultTransport = new ResultTransport();

        long allOrdersTotal = 0;
//      allOrdersTotal += orderService.countNotFinishedByPassenger(passengerId);
        ServiceSetting checkOpen = ServiceUtil.checkOpen();

        Map<String, String> kv = new HashMap<String, String>();
        if (null != passengerId) {
            kv.put("passengerId", String.valueOf(passengerId));
            kv.put("status", "nocancel");
        }

        if (checkOpen.isZhuanche()) {
            StringBuilder zhuanBuilder = new StringBuilder();
            zhuanBuilder.append(zhuanApi.getZhuanBaseURL())
                .append(ZhuanApi.COUNT_TODAYORDER_BY_PASSENGER).append(".json?appKey={appKey}")
                .append("&passengerId={passengerId}").append("&status={status}");
            long zhuanOrdersTotal = RETUnFinish(2, zhuanBuilder.toString(), kv);
            allOrdersTotal += zhuanOrdersTotal;
        }
        if (checkOpen.isPaotui()) {
            StringBuilder errandBuilder = new StringBuilder();
            errandBuilder.append(errandApi.getErrandBaseURL())
                .append(ErrandApi.COUNT_TODAYORDER_BY_PASSENGER).append(".json?appKey={appKey}")
                .append("&passengerId={passengerId}").append("&status={status}");
            long errandOrdersTotal = RETUnFinish(3, errandBuilder.toString(), kv);
            allOrdersTotal += errandOrdersTotal;
        }
//        if (checkOpen.isFreight()) {
//          StringBuilder freightBuilder = new StringBuilder();
//          freightBuilder.append(freightApi.getFreightBaseURL()).append(FreightApi.COUNT_TODAYORDER_BY_PASSENGER).append(".json?appKey={appKey}").append("&passengerId={passengerId}").append("&status={status}");
//          long freightOrdersTotal = RETUnFinish(4, freightBuilder.toString(), kv);
//          allOrdersTotal +=freightOrdersTotal;
//        }
//        if (checkOpen.isZhuanxian()) {
//          StringBuilder zhuanxianBuilder = new StringBuilder();
//          zhuanxianBuilder.append(zhuanxianApi.getZhuanxianBaseURL()).append(ZhuanxianApi.COUNT_TODAYORDER_BY_PASSENGER).append(".json?appKey={appKey}").append("&passengerId={passengerId}").append("&status={status}");
//          long zhuanxianOrdersTotal = RETUnFinish(5, zhuanxianBuilder.toString(), kv);
//          allOrdersTotal +=zhuanxianOrdersTotal;
//        }

        if (allOrdersTotal > 0) {
            resultTransport.setCode(-86);
            resultTransport.setData(allOrdersTotal);
            resultTransport.setMessage("有未完成的订单");
        } else {
            resultTransport.setCode(0);
            resultTransport.setMessage("无未完成订单");
        }

        Gson gson = new Gson();
        return resultTransport;
    }

    public long RETUnFinish(int api, String bu, Map<String, String> kv) {

        Gson gson = new Gson();

        String result = null;
        switch (api) {
            case 2:
                result = zhuanApi.get(bu, kv, settingUtils.get());
                break;
            case 3:
                result = errandApi.get(bu, kv, settingUtils.get());
                break;
            case 4:
                result = freightApi.get(bu, kv, settingUtils.get());
                break;
            case 5:
                result = zhuanxianApi.get(bu, kv, settingUtils.get());
                break;
            default:
                result = null;
                break;
        }

        long total = 0;
        if (null != result) {
            JSONObject jo = new JSONObject(result);
            Integer code = jo.getInt("code");
            if (code == 0) {
                total += jo.getLong("data");
            }
        }
        return total;

    }

    /**
     * 获取后台设置的预约时间
     */
    @RequestMapping(value = "getZhuanYuyueTime", method = RequestMethod.GET)
    public @ResponseBody
    ResultTransport getZhuanYuyueTime() {
        Setting setting = settingUtils.get();
        Integer bookTimeZhuan = setting.getBookTimeZhuan();
        int i = bookTimeZhuan * 60 * 1000;
        ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
        instance.setData(i);
        return instance;
    }

    @RequestMapping(value = "getAllOrderByPassengerId", method = RequestMethod.GET)
    @ResponseBody
    public ResultTransport getAllOrderByPassengerId(Long passengerId, Integer page, Integer rows) {
        ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
        Setting setting = settingUtils.get();
        ServiceSetting serviceSetting = ServiceUtil.checkOpen();
        List<Map<String, Object>> list = new ArrayList<>();
        if (serviceSetting.isZhuanche()) {
            List<Map<String, Object>> maps = new ArrayList<>();
            List<Order> orders = zhuanApi.findOrdersV4up(passengerId, page, rows, 1, setting);
            for (Order order : orders) {
                Map<String, Object> map = object2Map(order);
                maps.add(map);
            }
            list.addAll(maps);
        }
        if (serviceSetting.isPaotui()) {
            List<Map<String, Object>> maps = (List<Map<String, Object>>) errandApi
                .findByStatusV2(passengerId, page, rows, setting);
            list.addAll(maps);
        }
        if (serviceSetting.isDaijia()) {
            List<Map<String, Object>> maps = (List<Map<String, Object>>) orderService
                .findByParams(passengerId, page, rows).get("orderList");
            list.addAll(maps);
        }
        if (serviceSetting.isZhuanxian()) {
            List<Map<String, Object>> maps = (List<Map<String, Object>>) freightApi
                .findOrders(passengerId, page, rows, setting.getSecKey());
            list.addAll(maps);
        }
        if (serviceSetting.isFreight()) {
            List<Map<String, Object>> maps = zhuanxianApi
                .findOrderByPassenge(passengerId, page, rows, setting);
            list.addAll(maps);
        }

        Collections.sort(list, new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                try {
                    Date o1Date = new Date((Long) (o1.get("serverTime")));
                    Date o2Date = new Date((Long) (o2.get("serverTime")));
                    return o1Date.compareTo(o2Date);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return 0;
            }
        });

        instance.setData(list);
        return instance;
    }

    public Map<String, Object> object2Map(Object o) {
        Map<String, Object> map = new HashMap<>();
        Class cls = o.getClass();
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                Object obj = field.get(o);
                map.put(field.getName(), obj == null ? null : String.valueOf(obj));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return map;
    }

}
